package info.batcloud.fanli.core.service.impl;

import com.ctospace.archit.common.pagination.Paging;
import info.batcloud.fanli.core.dto.FootmarkDTO;
import info.batcloud.fanli.core.entity.CommissionItem;
import info.batcloud.fanli.core.entity.Footmark;
import info.batcloud.fanli.core.entity.Item;
import info.batcloud.fanli.core.enums.FootmarkType;
import info.batcloud.fanli.core.helper.PagingHelper;
import info.batcloud.fanli.core.repository.FootmarkRepository;
import info.batcloud.fanli.core.service.FootmarkService;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.inject.Inject;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import java.util.Date;
import java.util.List;

@Service
public class FootmarkServiceImpl implements FootmarkService {

    @Inject
    private FootmarkRepository footmarkRepository;

    @Override
    public void addFootmark(long userId, long itemId, FootmarkType type) {
        Footmark footmark = footmarkRepository.findByUserIdAndItemIdAndType(userId, itemId, type);
        if (footmark == null) {
            footmark = new Footmark();
            CommissionItem item = new CommissionItem();
            item.setId(itemId);
            footmark.setItem(item);
            footmark.setType(type);
            footmark.setUserId(userId);
        }
        footmark.setCreateTime(new Date());
        footmarkRepository.save(footmark);
    }

    @Override
    @Transactional
    public void deleteByUserIdAndItemId(long userId, long id) {
        footmarkRepository.deleteByUserIdAndItemId(userId, id);
    }

    @Override
    @Transactional
    public void clearByUserId(long userId) {
        footmarkRepository.deleteByUserId(userId);
    }

    @Override
    public boolean toggleFavor(long userId, long itemId) {
        Footmark footmark = footmarkRepository.findByUserIdAndItemIdAndType(userId, itemId, FootmarkType.FAVOR);
        if(footmark != null) {
            footmarkRepository.delete(footmark);
            return false;
        } else {
            addFootmark(userId, itemId, FootmarkType.FAVOR);
            return true;
        }
    }

    @Override
    public boolean isFavor(long userId, long itemId) {
        return footmarkRepository.countByUserIdAndItemIdAndType(userId, itemId, FootmarkType.FAVOR) > 0;
    }

    @Override
    public Paging<FootmarkDTO> search(SearchParam param) {
        Specification<Footmark> specification = (root, query, cb) -> {
            Predicate predicate = cb.conjunction();
            List<Expression<Boolean>> expressions = predicate.getExpressions();
            if (StringUtils.isNotBlank(param.getKeywords())) {
                expressions.add(cb.like(root.get("item").get("title"), "%" + param.getKeywords() + "%"));
            }
            if (param.getUserId() != null) {
                expressions.add(cb.equal(root.get("userId"), param.getUserId()));
            }
            if (param.getType() != null) {
                expressions.add(cb.equal(root.get("type"), param.getType()));
            }
            return predicate;
        };
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");

        Pageable pageable = new PageRequest(param.getPage() - 1,
                param.getPageSize(), sort);
        Page<Footmark> page = footmarkRepository.findAll(specification, pageable);
        return PagingHelper.of(page, item -> toDto(item), param.getPage(), param.getPageSize());
    }

    private FootmarkDTO toDto(Footmark footmark) {
        FootmarkDTO dto = new FootmarkDTO();
        dto.setId(footmark.getId());
        dto.setCreateTime(footmark.getCreateTime());
        dto.setUserId(footmark.getUserId());
        Item item = footmark.getItem();
        dto.setItemId(item.getId());
        dto.setItemOriginPrice(item.getOriginPrice());
        dto.setItemEcomPlat(item.getEcomPlat());
        dto.setItemPicUrl(item.getPicUrl());
        dto.setItemPrice(item.getPrice());
        dto.setItemTitle(item.getTitle());
        dto.setItemType(item.getClass().getSimpleName());
        return dto;
    }
}
